import MathEx from '../../../Core/Math/MathEx';
import { L } from '../../Common/Language';
import { JXLocales } from '../../Common/Zh';
import { JXRandom } from './../../../conventions/JXCommon';
import { ObjectWrap } from './../../../Core/FrameEx/ES5Ex';
import { CMsg } from './../../Common/Define';
import { JXBattleAnalysis } from './JXBattleAnalysis';
import { JXBattleCb } from './JXBattleCb';
import { ERR_CB_UN_READY, JXBtlAns_Result, JXBtlCamp } from './JXBattleDefine';
import { JXBattleAmbienter, JXBattleEntity } from './JXBattleRole';
import { JXBattleBuff } from './JXBattleSkill';
import { JXBattleStep } from './JXBattleStep';
import JXBattleTeam from './JXBattleTeam';
import JXRBCmdMgr from './JXRBCmdMgr';


export default class JXBtlMgr extends ObjectWrap {
    protected static _ins: JXBtlMgr;

    public static get ins(): JXBtlMgr {
        if (!this._ins) {
            this._ins = new JXBtlMgr();
        }
        return this._ins;
    }
    /** 战斗结束回调 */
    protected _endCb: { (analysis: JXBattleAnalysis): void };
    private _anlysis: JXBattleAnalysis = null;
    public get anlysis(): JXBattleAnalysis {
        return this._anlysis;
    }
    private _teams: [JXBattleTeam, JXBattleTeam];
    /** 随机类 */
    public random: JXRandom;
    public static cbReady(): boolean {
        return !!JXBattleCb.getPrng && !!JXBattleCb.getCardData && !!JXBattleCb.getSkillData && !!JXBattleCb.getBuffData && JXBattleCb.getUnitData && !!JXBattleCb.getEffectData;
    }
    /** 全局环境对象 */
    protected _ambientEntitys: JXBattleEntity[];
    private _cmdMgr: JXRBCmdMgr = null;
    /** 衍生事件，如果存在衍生事件，则当前主执行顺序执行完成之后，将会进行衍生事件的处理，
     * 衍生事件处理完成之后才会继续处理主执行队列
    **/
    protected _stepActions: JXBattleStep[] = [];

    /** 需要在下一次操作周期进行移除的BUFF */
    protected _waitRemoveBuffs: JXBattleBuff[] = []
    public addRemoveBuff(buff: JXBattleBuff) {
        if (!this._waitRemoveBuffs) this._waitRemoveBuffs = [];
        this._waitRemoveBuffs.push(buff);
    }

    //敌我方行动次数
    protected actionCount = {
        attker: 0,
        defens: 0,
    }

    /** 根据阵营，获取队伍 */
    public getTeamByCamp(camp: number): JXBattleTeam {
        return this._teams[camp];
    }
    /** 战斗接口(user & user) */
    public fight(atkerTeam: IMonsterBtl, defTpl: IMonsterBtl, btl: JXRBCmdMgr, seed?: string, endCb?: { (analysis: JXBattleAnalysis): void }): JXBattleAnalysis {
        if (!JXBtlMgr.cbReady()) {
            throw new Error(ERR_CB_UN_READY);
        }
        this._endCb = endCb;
        this._cmdMgr = btl
        this.random = new JXRandom(JXBattleCb.getPrng, seed);
        let empty: IMonsterBtl = {
            heroIds: [],
            partnerData: [],
            tableIds: []
        }
        this._anlysis = new JXBattleAnalysis([atkerTeam, empty], defTpl);
        this._teams = [new JXBattleTeam(atkerTeam, JXBtlCamp.Attacker, btl), new JXBattleTeam(defTpl, JXBtlCamp.Defenser, btl)];
        this._ambientEntitys = [];
        this._ambientEntitys.push(new JXBattleAmbienter([], 0));
        this._ambientEntitys.push(this._teams[JXBtlCamp.Attacker].ambienter);
        this._ambientEntitys.push(this._teams[JXBtlCamp.Defenser].ambienter);
        /** TODO： 战斗实际过程 */
        this._anlysis.randomSeed = this.random.seed.toString();
        return this._anlysis;
    }

    update(dt) {
        if (this.isEndFight()) {
            this._cmdMgr.pauseCmd();
            this._cmdMgr.evtMgr.post(CMsg.client.fight_ui.end_fight);
            return;
        }

        let allTeam = [];
        allTeam.push(...this._teams[JXBtlCamp.Defenser].roles.values())
        allTeam.push(...this._teams[JXBtlCamp.Attacker].roles.values())
        allTeam = MathEx.fisherYatesShuffle(allTeam);
        allTeam.forEach(role => {
            role.update(dt)
        })
    }

    /** 检测是否结束战斗 */
    public isEndFight(): boolean {
        let roles = this._teams[JXBtlCamp.Attacker].getRoles(v => !v.isDie);
        let isEnd = this._cmdMgr.monsterFactory.isProduceEnd;
        let isProduce = this._cmdMgr.monsterFactory.isProduce;
        if (roles.length === 0 && isProduce && !isEnd) {
            let isChange = this._cmdMgr.monsterFactory.nextWave();
            if (isChange) {
                this._cmdMgr._wave.string = L(JXLocales.fight.wave, this._cmdMgr.monsterFactory.waveNum + 1);
            } else {
                this._cmdMgr._wave.string = L(JXLocales.fight.wave, this._cmdMgr.monsterFactory.waveNum);
            }
            return false;
        }
        if (this.anlysis.barrackHps <= 0) {
            this._anlysis.setDefResult(JXBtlAns_Result.Lost);
            this._cmdMgr.isEnd = true;
            return true;
        } else
            if (roles.length == 0 && isEnd && this._anlysis.barrackHps > 0 && isProduce) {
                /** 分析结果 */
                this._anlysis.setDefResult(JXBtlAns_Result.Win);
                this._cmdMgr.isEnd = true;
                return true;
            }
        return false;
    }

    /** 获取所有的队伍参战对象 */
    public getAllRoles(includeDie: boolean = false): JXBattleEntity[] {
        let roles: JXBattleEntity[] = [];
        for (let i = 0; i < this._teams.length; i++) {
            roles.push(...this._teams[i].getRoles(v => includeDie ? true : !v.isDie));
        }
        return roles;
    }


    public getEntityById(herId): JXBattleEntity {
        if (!herId) {
            cc.error("no heroid");
            return null;
        }
        for (let i = 0; i < this._teams.length; i++) {
            let roles = this._teams[i].getRoles();
            for (let j = 0; j < roles.length; j++) {
                if (roles[j].id == herId) {
                    return roles[j];
                }
            }
        }
        return null;
    }
    /** 获取所有实例对象 */
    public getAllEntitys(includeDie: boolean = false) {
        let entitys = this.getAllRoles(includeDie);
        for (let i = 0; i < this._ambientEntitys.length; i++) {
            if (includeDie || !this._ambientEntitys[i].isDie) {
                entitys.push(this._ambientEntitys[i]);
            }
        }
        return entitys;
    }

    /** 清理缓存的BUFF */
    public cleanWaitRemoveBuffs() {
        for (let i = 0; i < this._waitRemoveBuffs.length; i++) {
            this._waitRemoveBuffs[i].destroy();
        }
        this._waitRemoveBuffs.length = 0;
    }

    /** 插入一个执行步骤 */
    public addStep(step: JXBattleStep) {
        this._stepActions.push(step);
    }

    /** 执行 */
    public workSteps() {
        if (!this._stepActions || this._stepActions.length == 0) return;
        let top = this._stepActions.shift();
        top.exec();
        top.completed();
        JXBtlMgr.ins.cleanWaitRemoveBuffs();
        if (this._stepActions.length > 0) {
            this.workSteps();
        }
    }


    /** 筛选存在的动作的实体类 */
    protected getRoleQueue(): JXBattleEntity[] {
        let roles = this.getAllEntitys(true);

        return roles;
    }

    /** */
    public getAkerLifeNum() {
        let num = 0;
        for (let i = 0; i < this._teams.length; i++) {
            if (this._teams[i].camp == JXBtlCamp.Attacker) {
                let roles = this._teams[i].roles.values();
                for (let j = 0; j < roles.length; j++) {
                    if (!roles[j].isDie) {
                        num++;
                    }
                }
            }
        }
        return num;
    }

    public onEvent(eventType: number, ...eventParams: any[]) {
        this._anlysis.write(eventType, ...eventParams);
        JXBattleCb.evtEmitCb && JXBattleCb.evtEmitCb(eventType, ...eventParams);
    }

}